#!/usr/bin/env ruby

require 'fileutils'

# Create the compiled locales directory.
# You can specify it as COMPILED_LOCALES_DIR in the environment,
# or it will be $SRCROOT/__Compiled Locales.
compiledDir = ENV['COMPILED_LOCALES_DIR'] || File.join(ENV['SRCROOT'], '__Compiled Locales')

Dir.mkdir(compiledDir) unless File.directory? compiledDir

# Get the locales source dir.
# You can specify it as LOCALES_DIR, but by default it's
# $SRCROOT/Locales

localesDir = ENV['LOCALES_DIR'] || File.join(ENV['SRCROOT'], 'Locales')

# Each directory inside localesDir is a locale. It must
# be a Mac OS X-understood locale code (eg Italian or it),
# without .lproj.

locales = []
Dir.open(localesDir) do |d|
  # non-hidden (non-.) directories are locales
  locales = d.entries.select { 
    |x| x.match(/^[^.]/) and File.directory?(File.join(localesDir, x))
    }
end

# Get the base locale dir. It's either in the env as
# BASE_LOCALE_DIR; or it's en.lproj; or it's English.lproj.

ISO_NAMED_DIR = File.join(ENV['SRCROOT'], 'en.lproj')
NEXT_NAMED_DIR = File.join(ENV['SRCROOT'], 'English.lproj')

dirPath =
  (ENV['BASE_LOCALE_DIR'] if ENV['BASE_LOCALE_DIR']) ||
  (NEXT_NAMED_DIR if File.directory? NEXT_NAMED_DIR) ||
  (ISO_NAMED_DIR if File.directory? ISO_NAMED_DIR)

raise "error: #{dirPath} is not a directory or doesn't exist" unless File.directory? dirPath

# compiledLocaleDirs contains the .lproj folders in the
# compiledDir for each locale (locale name -> lproj path)

compiledLocaleDirs = {}
locales.each do |locale|
  compiledLocaleDir = File.join(compiledDir, locale + '.lproj')
  Dir.mkdir(compiledLocaleDir) unless File.directory? compiledLocaleDir
  compiledLocaleDirs[locale] = compiledLocaleDir
end

# The meat of the thing -- iterate the source files and for
# each do some work with the localization.

Dir.open(dirPath).each do |file|
  fullFilePath = File.join(dirPath, file)
  case file
    
  when /\.nib$/, /\.xib$/
    
    # This is slightly tricky. We need ibtool to run and
    # make us a very, very nice compiled .nib file out of
    # the nib or xib.
    compiledNibName = file[0, file.length - 3] + 'nib';

    compiledLocaleDirs.each do |locale, compiledLocaleDir|
      stringsFile = File.join(localesDir, locale, file + '.strings')
      
      # This is hackish -- ideally, we'd fail if there's no
      # .strings file, but some NIB files have no localizable content
      # so we mark them by removing their .strings file from
      # the locale dir.
      if File.exists? stringsFile
      
        compiledNibFile = File.join(compiledLocaleDir, compiledNibName)
        if File.exist? compiledNibFile and File.stat(compiledNibFile).mtime < File.stat(fullFilePath).mtime
            $stderr.puts "note: Removing file #{compiledNibFile} because the source file #{fullFilePath} is updated."
            File.delete compiledNibFile
        end
        
        # Also: rebuild if the .strings file has changed.
         if File.exist? compiledNibFile and File.stat(compiledNibFile).mtime < File.stat(stringsFile).mtime
            $stderr.puts "note: Removing file #{compiledNibFile} because the strings file #{stringsFile} is updated."
            File.delete compiledNibFile
        end
      
        unless File.exist? compiledNibFile
          $stderr.puts "note: #{compiledNibFile} does not exist, regenerating."
          commandLine = ['/usr/bin/ibtool',
            '--agent-name', 'net_infinite_labs_BuildLocaleIBToolAgent',
            '--agent-timeout', '30',
            '--strings-file', stringsFile,
            '--compile', compiledNibFile,
            fullFilePath]
          $stderr.puts "Calling: #{commandLine.join ' '}"
          fork do
            exec(*commandLine)
          end
          Process.wait
        end
      end
    end
 
  when /\.strings$/
    # ignore xxx.nib.strings or yyy.xib.strings -- generated by CollectLocale.
    unless file =~ /\.nib\.strings$/ or file =~ /\.xib\.strings$/
    
      # Copy the localized file from the localeDir to the compiledLocaleDir
      compiledLocaleDirs.each do |locale, compiledLocaleDir|
        compiledStringsFile = File.join(compiledLocaleDir, file)
      
        if File.exist? compiledStringsFile and File.stat(compiledStringsFile).mtime < File.stat(fullFilePath).mtime
          $stderr.puts "note: Removing file #{compiledStringsFile} because the source file #{fullFilePath} is updated."
          File.delete compiledStringsFile
        end
      
        unless File.exist? compiledStringsFile
          $stderr.puts "note: #{compiledStringsFile} does not exist, regenerating."
          FileUtils.cp File.join(localesDir, locale, file),
            compiledStringsFile
        end
      end
    end
  end
end
